abstract case class Direction(x: Int, y: Int) {
	def opposite: Direction
}

case object Up extends Direction(0, -1) {
	def opposite: Direction = Down
}

case object Left extends Direction(1, 0) {
	def opposite: Direction = Right
}

case object Down extends Direction(0, 1) {
	def opposite: Direction = Up
}

case object Right extends Direction(-1, 0) {
	def opposite: Direction = Left
}

case class Position(x: Int, y: Int) {
	require(x >= 0 && y >= 0)

	def +(dir: Direction) = Position(x + dir.x, y + dir.y)
}

trait Pipe {
	def fitsIn(dir: Direction): Option[Direction]
}

case class Source(pos: Position, dir: Direction) extends Pipe {
	def fitsIn(dir: Direction) = None
}

case class Horizontal extends Pipe {
	def fitsIn(dir: Direction): Option[Direction] = {
		dir match {
			case Left => Some(Right)
			case Right => Some(Left)
			case _ => None
		}
	}
}

case class State(
	grid: List[List[Option[Pipe]]],
	pos: Position,
	dir: Direction,
	steps: List[Pipe],
	pipesLeft: List[Pipe]) {

	def nextStep: List[State] = {
		for {
			pipe <- pipesLeft.distinct
			direction = pipe.fitsIn(dir)
			if (direction.isDefined)
		} yield newState(pipe, direction.get)
	}

	private def newState(pipe: Pipe, direction: Direction) = State(updateGrid(grid, pos, pipe), pos + dir, direction, steps :+ pipe, pipesLeft - pipe)
	private def updateGrid(grid: List[List[Option[Pipe]]], pos: Position, pipe: Pipe): List[List[Option[Pipe]]] = grid.updated((pos.x), grid(pos.x).updated(pos.y, Some(pipe)))

	def isSolution: Boolean = pos.x < 0 || pos.y < 0 || pos.x >= grid.length || pos.y >= grid.length
}

class Motor(
	dim: (Int, Int),
	source: Source,
	pipes: List[Pipe]) {

	import scala.collection.mutable.MutableList

	def run() {
		
		var state: State = State(initGrid, source.pos, source.dir, List(), pipes)
		
		while(!state.isSolution){
			for (State <- nextState) {
				
			}
		}
	}
	
	def initGrid = {
		val grid: MutableList[MutableList[Option[Pipe]]] = MutableList()

		for (i <- 0 to dim._1) {
			for (j <- 0 to dim._2) {
				grid(i)(j) = None
			}
		}
		grid(source.pos.x)(source.pos.y) = Some(source)
		grid.map(_.toList).toList
	}
	
}

object App extends App {
	println("Hola Mundo!")
}